package cc.shacocloud.mirage.restful.bind.validation;

import cc.shacocloud.mirage.restful.bind.validation.errors.BindingResultError;
import cc.shacocloud.mirage.restful.bind.validation.errors.DefaultBindingResultError;
import cc.shacocloud.mirage.utils.ObjectUtil;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 思追(shaco)
 */
public abstract class AbstractBindingResult implements BindingResult {
    
    @Getter
    @NotNull
    private final Object target;
    @NotNull
    protected List<BindingResultError> bindingResultErrors;
    
    public AbstractBindingResult(@NotNull Object target) {
        this(target, new ArrayList<>());
    }
    
    public AbstractBindingResult(@NotNull Object target, @NotNull List<BindingResultError> bindingResultErrors) {
        this.target = target;
        this.bindingResultErrors = bindingResultErrors;
    }
    
    @Override
    public boolean hasErrors() {
        return bindingResultErrors.size() > 0;
    }
    
    @Override
    public int getErrorCount() {
        return bindingResultErrors.size();
    }
    
    @Override
    public List<BindingResultError> getAllErrors() {
        return bindingResultErrors;
    }
    
    @Override
    public void rejectValue(@NotNull String nestedPath, @NotNull String errorCode) {
        Object rejectedValue = ObjectUtil.getNestedPathValue(target, nestedPath);
        bindingResultErrors.add(new DefaultBindingResultError(errorCode, nestedPath, rejectedValue));
    }
    
    @Override
    public void rejectValue(@NotNull String nestedPath, @NotNull String @NotNull ... errorCodes) {
        Object rejectedValue = ObjectUtil.getNestedPathValue(target, nestedPath);
        for (String errorCode : errorCodes) {
            bindingResultErrors.add(new DefaultBindingResultError(errorCode, nestedPath, rejectedValue));
        }
    }
    
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(getClass().getName());
        sb.append(": ").append(getErrorCount()).append(" 个错误");
        for (BindingResultError error : getAllErrors()) {
            sb.append('\n').append(error);
        }
        return sb.toString();
    }
}
